/*
Copyright 乘风飞鹤
Flying JS library
Mail cffhidol@163.com cffhidol@gmail.com
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
*/
class FlyHTML {
   constructor(eles) {
      Object.defineProperties(this, {
         length: {
            value: 0,
            configurable: true,
            writable: true
         }
      });
   }
   ;
   f(str) {
      var neles = new FlyHTML;
      return flying._selector.shell(flying._selector.structure(this.childs, str, neles));
   }
   d(str) {
      var neles = new FlyHTML;
      return flying._selector.shell(flying._selector.structure(this.child, str, neles));
   }
   p(str) {
      var neles = new FlyHTML;
      return flying._selector.shell(flying._selector.structure(this.parents, str, neles));
   }
   b(str) {
      var neles = new FlyHTML;
      return flying._selector.shell(flying._selector.structure(this.brother, str, neles));
   }
   on(type, listener) {
      if (typeof type === 'string') {
         for (const i in this) {
            this[i].addEventListener(type, listener);
         }
      }
      else {
         let o = {};
         for (const k in type) {
            for (const v of this) {
               v.addEventListener(k, type[k]);
            }
         }
      }
      return this;
   }
   get child() {
      let eles = new FlyHTML;
      for (let v of this) {
         eles.push(...v.child);
      }
      return eles;
   }
   get childs() {
      let eles = new FlyHTML;
      for (let v of this) {
         eles.push(...v.getElementsByTagName('*'));
      }
      return eles;
   }
   get parents() {
      let eles = new FlyHTML;
      for (let v of this) {
         let ele = v.parent;
         while (ele !== document) {
            eles.push(ele);
            ele = ele.parent;
         }
      }
      return eles;
   }
   get brother() {
      let eles = new FlyHTML;
      for (let v of this) {
         eles.push(v.parentNode.child);
      }
      return eles;
   }
   forEach(callback) { Array.prototype.forEach.call(this, callback); }
   push(...a) { Array.prototype.push.call(this, ...a); }
   slice(...a) { Array.prototype.slice.call(this, ...a); }
   splice(...a) { Array.prototype.splice.call(this, ...a); }
   map(callback) {
      let arr = [];
      for (let i = 0; i < this.length; i++) {
         arr.push(callback(this[i], i, this));
      }
      return arr;
   }
   filter(callback) {
      var eles = new FlyHTML;
      for (var i = 0; i < this.length; i++) {
         if (callback(i, this[i], this))
            eles.push(this[i]);
      }
      return eles;
   }
   merge(eles) {
      if (!eles)
         return;
      for (let i = 0; i < eles.length; i++) {
         this.push(eles[i]);
      }
      return this;
   }
   empty() {
      for (let i in this) {
         delete this[i];
      }
      this.length = 0;
   }
   remove() {
      for (let v of this) {
         v.remove();
      }
      this.empty();
   }
   addhtml(html, str) {
      for (let x of this) {
         x.addhtml(html, str);
      }
      return this
   }
   addClass(...str) {
      for (let v of this) {
         v.classList.add(...str);
      }
      return this
   }
   removeClass(...str) {
      for (let v of this) {
         v.classList.remove(...str);
      }
      return this
   }
   boolClass(str, bl) {
      for (let v of this) {
         bl ? v.classList.add(str) : v.classList.remove(str);
      }
      return this
   }
   toggleClass(str) {
      for (let v of this) {
         v.hasClass(str) ?
            v.removeClass(str) :
            v.addClass(str)
      }
      return this
   }
   attr(a, b) {
      if (b) {
         this.forEach(t => t.attr(a, b))
      } else {
         let ar = []
         this.forEach(t => ar.push(t.attr(a)))
      }
   }
   prop(a, b) {
      if (b) {
         this.forEach(t => t.prop(a, b))
      } else {
         let ar = []
         this.forEach(t => ar.push(t.prop(a)))
      }
   }
   show() {
      for (const v of this) {
         v.style.display = 'none'
      }
   }
   hidden() {
      for (const v of this) {
         v.style.display = ''
      }
   }
   toString() {
      return JSON.stringify([...this])
   }
   get css() {
      return new Proxy({}, {
         set: (a, key, val) => {
            if (/width|height|left|right|top|bottom/.test(key) && typeof val === 'number')
               val = val + 'px';
            for (let x of this) {
               x.style[key] = val;
            }
            return true;
         }
      });
   }
   set css(object) {
      for (let key in object) {
         this.css[key] = object[key];
      }
   }
   get html() {
      let arr = [];
      for (let i = 0; i < this.length; i++) {
         arr.push(this[i].innerHTML);
      }
      return arr;
   }
   set html(str) {
      if (typeof str === 'object') {
         let s = ''
         for (let k in str) s += str[k]
         str = s
      }
      for (let x of this) {
         x.innerHTML = str;
      }
   }
   get text() {
      let arr = [];
      for (let i = 0; i < this.length; i++) {
         arr.push(this[i].innerText);
      }
      return arr;
   }
   set text(str) {
      for (let x of this) {
         x.innerText = str;
      }
   }
}
{
   /**
    * Flying模块顶级对象、Flying选择器
    */
   const flying = function (str) {
      if (!str) {
         const eles = new FlyHTML;
         eles.push(...document.getElementsByTagName('*'));
         return eles;
      }
      if (typeof str === 'function') {
         window.addEventListener('DOMContentLoaded', str);
         return;
      }
      //focus返回当前焦点元素
      if (str === 'focus') {
         return document.activeElement;
      }
      let neles = new FlyHTML;
      return flying._selector.shell(flying._selector.structure(document.getElementsByTagName('*'), str, neles));
   };
   Symbol.iterator, Symbol.toStringTag;
   FlyHTML.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
   FlyHTML = FlyHTML;
   flying._selector = {
      indexStr(str, key, i) {
         let s = '';
         for (; i < str.length; i++) {
            const v = str[i];
            if (key.test(v))
               return { s, v, i };
            s += v;
         }
         return { s };
      },
      shell: function (eles) {
         //判断唯一性
         return eles.length === 1 ? eles[0] : eles;
      },
      structure(eles, str, neles) {
         //结构分析器
         let a = { i: 0 }, e = eles, r = /[ <>,+~]/;
         while (true) {
            a = this.indexStr(str, r, a.i);
            a.i++;
            if (!a.v) {
               return this.subject(e, a.s, neles);
            }
            if (e === eles)
               e = this.subject(e, a.s, new FlyHTML);
            if (a.v === ' ') {
               e = this.subject(e, a.s, new FlyHTML);
               e = e.childs;
            }
            else if (a.v === '>') {
               e = this.subject(e, a.s, new FlyHTML);
               e = e.child;
            }
            else if (a.v === '<') {
               e = this.subject(e, a.s, new FlyHTML);
               e = e.parents;
            }
            else if (a.v === '+') {
               e = this.subject(e, a.s, new FlyHTML);
               let ne = new FlyHTML;
               for (const v of e) {
                  ne.push(v.nextElementSibling);
               }
               e = ne;
            }
            else if (a.v === '~') {
               e = this.subject(e, a.s, new FlyHTML);
               const ne = new FlyHTML;
               for (const v of e) {
                  let bl = false;
                  v.brother.forEach((a) => {
                     if (bl)
                        ne.push(a);
                     v.isSameNode(a) && (bl = true);
                  });
               }
               e = ne;
            }
            else if (a.v === ',') {
               this.subject(e, a.s, neles);
               e = eles;
            }
         }
      },
      key(str) {
         //分析选择器关键词
         let tag = '', css = [], att = [], key = [], i = 0;
         for (; i < str.length; i++) {
            const v = str[i];
            if (v === '.' || v === '[' || v === ':')
               break;
            tag += v;
         }
         for (; i < str.length; i++) {
            const v = str[i];
            if (v === '[' || v === ':')
               break;
            if (v === '.') {
               css.push('');
               continue;
            }
            css[css.length - 1] += v;
         }
         att = [];
         for (; i < str.length; i++) {
            const v = str[i];
            const j = att.length - 1;
            if (v === ':')
               break;
            if (/[<>=$!]/.test(v)) {
               att[j].o += v;
               att[j].v = '';
               continue;
            }
            if (v === '[') {
               att.push({ k: '', o: '' });
               continue;
            }
            if (v === ']') {
               continue;
            }
            if (att[j].v === undefined) {
               att[j].k += v;
            }
            else {
               att[j].v += v;
            }
         }
         key = [];
         for (; i < str.length; i++) {
            const v = str[i];
            if (v === ':') {
               key.push('');
               continue;
            }
            key[key.length - 1] += v;
         }
         return { tag, css, att, key }
      },
      subject(eles, str, neles) {
         if (!eles)
            return;
         //元素筛选器
         //例：f('tagName.class1.class2[key1=value1][key2=value2]:attr1:attr2')
         //id选择器直接返回该元素
         if (str[0] === '#') {
            const ne = document.getElementById(str.slice(1));
            if (ne) {
               neles.push(ne);
               return neles;
            }
            else {
               throw 'There is no HTMLElement of ' + str;
            }
         }
         let { tag, css, att, key } = this.key(str)
         //遍历元素集合匹配条件
         each: for (let i = 0, k = 0; i < eles.length; i++) {
            const ele = eles[i];
            if (tag) {
               if (ele.tagName !== tag.toUpperCase())
                  continue each;
            }
            if (css) {
               for (const v of css) {
                  if (!ele.classList.contains(v))
                     continue each;
               }
            }
            if (att) {
               for (const v of att) {
                  if (v.o === '=') {
                     if (ele.attr(v.k) != v.v)
                        continue each;
                  }
                  else if (v.o === '!=') {
                     if (ele.attr(v.k) == v.v)
                        continue each;
                  }
                  else if (v.o === '$=') {
                     const at = ele.attr(v.k);
                     if (!at || at.slice(-v.v.length) !== v.v)
                        continue each;
                  }
                  else {
                     if (!ele.attr(v.k))
                        continue each;
                  }
               }
            }
            if (key) {
               for (const v of key) {
                  const p = v.slice(0, 2);
                  if (p === 'gt') {
                     if (k <= this.indexStr(v, /[)]/, 3).s) {
                        k++;
                        continue each;
                     }
                  }
                  else if (p === 'lt') {
                     if (k >= this.indexStr(v, /[)]/, 3).s) {
                        k++;
                        break each;
                     }
                  }
                  else if (p === 'eq') {
                     if (k != this.indexStr(v, /[)]/, 3).s) {
                        k++;
                        continue each;
                     }
                     else {
                        neles.push(ele);
                        break each;
                     }
                  }
                  else if (v === 'first') {
                     neles.push(ele);
                     break each;
                  }
                  else if (v === 'last') {
                     if (k != 0)
                        neles.pop();
                  }
                  else if (v === 'even') {
                     if (k % 2) {
                        k++;
                        continue each;
                     }
                  }
                  else if (v === 'odd') {
                     if (!(k % 2)) {
                        k++;
                        continue each;
                     }
                  }
                  else if (v === 'header') {
                     if (!/H1|H2|H3|H4|H5|H6/.test(ele.tagName))
                        continue each;
                  }
                  else if (v === 'checked') {
                     if (!ele.checked)
                        continue each;
                  }
               }
            }
            k++;
            neles.push(ele);
         }
         return neles;
      },
      isKey(ele, str) {
         let { tag, css, att, key } = this.key(str)
         if (tag) {
            if (ele.tagName !== tag.toUpperCase())
               return false;
         }
         if (css) {
            for (const v of css) {
               if (!ele.classList.contains(v))
                  return false;
            }
         }
         if (att) {
            for (const v of att) {
               if (v.o === '=') {
                  if (ele.attr(v.k) != v.v)
                     return false;
               }
               else if (v.o === '!=') {
                  if (ele.attr(v.k) == v.v)
                     return false;
               }
               else if (v.o === '$=') {
                  const at = ele.attr(v.k);
                  if (!at || at.slice(-v.v.length) !== v.v)
                     return false;
               }
               else {
                  if (!ele.attr(v.k))
                     return false;
               }
            }
         }
         if (key) {
            for (const v of key) {
               const p = v.slice(0, 2);
               if (v === 'header') {
                  if (!/H1|H2|H3|H4|H5|H6/.test(ele.tagName))
                     return false;
               }
               else {
                  if (!ele[v])
                     return false;
               }
            }
            return true
         }
      }
   };
   flying.on = function (type, listener) {
      if (typeof type === 'string') {
         window.addEventListener(type, listener);
      }
      else {
         let o = {};
         for (const key in type) {
            window.addEventListener(key, type[key]);
         }
      }
   };
   flying.XML = {
      register(data) {
         return (typeof data === 'string') ? data : Object.entries(data).map(a => a.join('=')).join('&')
      },
      decode(data) {
         const arr = data.split('&')
         const obj = {}
         arr.forEach(a => {
            const ens = a.split('=')
            obj[ens[0]] = ens[1]
         })
         return obj
      }
   }
   flying.ajax = {
      getContentType(xml) {
         return xml.getResponseHeader('Content-Type').match(/.*\/.*(?=;)/, '')[0]
      },
      decode(xml) {
         const type = this.getContentType(xml)
         if (type === 'application/json') {
            return JSON.parse(xml.responseText)
         } else if (type === 'application/x-www-form-urlencoded') {
            return flying.XML.decode(xml.responseText)
         }
      },
      register(type, data) {
         if (type === 'application/json') {
            return JSON.stringify(data)
         } else if (type === 'application/x-www-form-urlencoded') {
            return flying.XML.register(data)
         }
      }
   }
   flying.contentType = 'application/json'
   flying.getJSON = function (url) {
      return new Promise((e, r) => {
         flying.get(url).then(a => { e(JSON.parse(a)) })
      })
   };
   flying.get = function (url, data) {
      return new Promise((e, r) => {
         try {
            let xml = new XMLHttpRequest();
            if (data) {
               url += '?' + flying.XML.register(data)
            }
            xml.open('get', url, true);
            xml.onload = function () {
               e(xml.responseText)
            }
            xml.send();
         } catch (err) {
            r(err)
         }
      })
   }
   flying.post = function (url, data) {
      return new Promise((e, r) => {
         try {
            if (typeof data !== 'string') data = flying.ajax.register(flying.contentType, data)
            let xml = new XMLHttpRequest();
            xml.open('post', url, true);
            xml.setRequestHeader("Content-Type", flying.contentType)
            xml.onload = function () {
               e(flying.ajax.decode(xml))
            }
            xml.send(data);
         } catch (err) {
            r(err)
         }
      })
   }
   flying.ajax = function ({
      url,
      method = 'get',

   }) {
      return new Promise((e, r) => {
         let xml = new XMLHttpRequest();
      })
   }
   Object.assign(HTMLElement.prototype, {
      f(str) {
         let neles = new FlyHTML;
         return flying._selector.shell(flying._selector.structure(this.getElementsByTagName('*'), str, neles));
      },
      d(str) {
         let neles = new FlyHTML;
         return flying._selector.shell(flying._selector.structure(this.child, str, neles));
      },
      p(str) {
         let neles = new FlyHTML;
         return flying._selector.shell(flying._selector.structure(this.parents, str, neles));
      },
      b(str) {
         let neles = new FlyHTML;
         return flying._selector.shell(flying._selector.structure(this.parent.child, str, neles));
      },
      on(type, listener) {
         if (typeof type === 'string') {
            this.addEventListener(type, listener);
            return () => {
               this.removeEventListener(type, listener);
            };
         }
         else {
            for (const k in type) {
               this.addEventListener(k, type[k]);
            }
         }
         return this;
      },
      en(type, str, listener) {
         if (typeof type === 'string') {
            this.addEventListener(type, (event) => {
               for (let ele = event.target; ele && !this.isEqualNode(ele); ele = ele.parentNode) {
                  if (flying._selector.isKey(ele, str)) {
                     listener.call(ele, event)
                     break;
                  }
               }
            })
         } else {
            for (const k in type) {
               this.en(k, str, type[k])
            }
         }
         return this
      },
      forEach(fun) {
         fun(this, 0);
      },
      map(fun) {
         return fun(this, 0);
      },
      filter(fun) {
         return fun(0, this) ? this : null;
      },
      win() {
         var d = this;
         var l = d.offsetLeft;
         var t = d.offsetTop;
         while (true) {
            d = d.offsetParent;
            if (!d) {
               l -= window.scrollX;
               t -= window.scrollY;
               return { top: t, left: l };
            }
            l += d.offsetLeft;
            l -= d.scrollLeft;
            t += d.offsetTop;
            t -= d.scrollTop;
         }
      },
      off() {
         var d = this;
         var l = d.offsetLeft;
         var t = d.offsetTop;
         while (true) {
            d = d.offsetParent;
            if (!d) {
               return { top: t, left: l };
            }
            l += d.offsetLeft;
            t += d.offsetTop;
         }
      },
      addhtml(html = '', str = 'end') {
         if (str === 'top' || str == 0) {
            this.insertAdjacentHTML('beforeBegin', html);
         }
         else if (str === 'start' || str == 1) {
            this.insertAdjacentHTML('afterBegin', html);
         }
         else if (str === 'end' || str == 2) {
            this.insertAdjacentHTML('beforeEnd', html);
         }
         else if (str === 'lower' || str == 3) {
            this.insertAdjacentHTML('afterEnd', html);
         }
         return this
      },
      isDisplay(str = 'd') {
         var ele = this;
         while (ele !== document) {
            if (/d/i.test(str) && window.getComputedStyle(ele).display === 'none')
               return false;
            if (/i/i.test(str) && window.getComputedStyle(ele).visibility === 'hidden')
               return false;
            if (/o/i.test(str) && window.getComputedStyle(ele).opacity === '0')
               return false;
            ele = ele.offsetParent;
         }
         return true;
      },
      attr(a, b) {
         if (b) {
            this.setAttribute(a, b);
         }
         return this.getAttribute(a)
      },
      prop(a, b) {
         if (b) {
            this[a]
         }
         return this[a]
      },
      addClass(...str) {
         this.classList.add(...str);
         return this;
      },
      removeClass(...str) {
         this.classList.remove(...str);
         return this;
      },
      boolClass(str, bl) {
         bl ? this.classList.add(str) : this.classList.remove(str);
         return this;
      },
      hasClass(str) {
         return this.classList.contains(str);
      },
      toggleClass(str) {
         this.hasClass(str) ?
            this.removeClass(str) :
            this.addClass(str)
         return this
      },
      singleClass(str) {
         let eles = this.brother
         for (let i = 0; i < eles.length; i++) {
            if (this.isSameNode(eles[i]))
               eles[i].addClass(str)
            else
               eles[i].removeClass(str)
         }
         return this
      },
      show() {
         this.style.display = ''
      },
      hide() {
         this.style.display = 'none'
      },
      isShow() {
         return this.style.display !== 'none'
      },
      length: 1
   });
   Object.defineProperties(HTMLElement.prototype, {
      '0': {
         get() {
            return this;
         }
      },
      css: {
         get() {
            return new Proxy({}, {
               get: (a, b) => {
                  return this.style[b];
               },
               set: (a, key, val) => {
                  if (/width|height|left|right|top|bottom/.test(key) && typeof val === 'number')
                     val = val + 'px';
                  this.style[key] = val;
                  return true;
               }
            });
         },
         set(object) {
            for (const key in object) {
               this.css[key] = object[key];
            }
         },
      },
      html: {
         get() {
            return this.innerHTML;
         },
         set(str) {
            if (typeof str === 'object') {
               let s = ''
               for (let k in str) s += str[k]
               str = s
            }
            this.innerHTML = str;
         }
      },
      text: {
         get() {
            return this.innerText;
         },
         set(str) {
            this.innerText = str;
         }
      },
      child: {
         get() {
            const eles = new FlyHTML;
            eles.push(...this.children);
            return eles;
         }
      },
      childs: {
         get() {
            const eles = new FlyHTML;
            eles.push(...this.getElementsByTagName('*'));
            return eles;
         }
      },
      parent: {
         get() {
            return this.parentNode;
         }
      },
      parents: {
         get() {
            let eles = new FlyHTML;
            let ele = this.parent;
            while (ele !== document) {
               eles.push(ele);
               ele = ele.parent;
            }
            return eles;
         }
      },
      brother: {
         get() {
            return this.parentNode.child;
         }
      },
      index: {
         get() {
            let eles = this.brother
            for (let i = 0; i < eles.length; i++) {
               if (this.isSameNode(eles[i])) return i
            }
         }
      }
   });
   function ranBool(num, len) {
      if (len) {
         var arr = new Array();
         for (var i = 0; i < len; i++) {
            arr.push(ranBool(num));
         }
         return arr;
      }
      else {
         return Math.random() * 100 < num;
      }
   }
   function ranNum(min, max, len) {
      if (len) {
         var arr = new Array();
         for (var i = 0; i < len; i++) {
            arr.push(ranNum(min, max));
         }
         return arr;
      }
      else {
         return Math.floor(Math.random() * (max - min) + min);
      }
   }
   function ranMap(a, num) {
      let b = a[0] !== undefined, c = a[2] !== undefined;
      if (num) {
         if (!b && c) { //(n - 0) / 1 * (te - ts) + ts = n * (te - ts) + ts
            return num * (a[3] - a[2]) + a[2];
         }
         else if (b && !c) { //(n - os) / (oe - os) * 1 + 0 = (n - os) / (oe - os)
            return (num - a[0]) / (a[1] - a[0]);
         }
         else {
            return (num - a[0]) / (a[1] - a[0]) * (a[3] - a[2]) + a[2];
         }
      }
      else {
         let xn = (a[1] - a[0]) / (a[3] - a[2]);
         return function (num) {
            return (num - a[0]) / (a[1] - a[0]) * (a[3] - a[2]) + a[2];
         };
      }
   }
   function meterTime(f, t, ...s) {
      let e = function (...c) {
         if (e['timeId']) {
            clearInterval(e['timeId']);
            e['timeId'] = 0;
         }
         else {
            e['timeId'] = setInterval(() => { f(...c); }, t);
         }
      };
      e(...s);
      return e;
   }
   class Count {
      constructor(cycle, execute = function () { }) {
         this.cnts = 0;
         this.cles = 0;
         this.cycle = cycle;
         this.execute = execute;
         this.bool = true;
      }
      count(execute) {
         this.cnts++;
         if (this.cnts === this.cycle) {
            if (execute) {
               this.execute = execute;
            }
            this.bool = !this.execute(this.cles, this.cycle);
         }
         if (this.cnts > this.cycle && this.bool) {
            this.cles++;
            this.cnts = 1;
         }
         return this.cnts;
      }
      static isCount(obj) {
         return obj instanceof Count;
      }
   }
   class delayExe {
      constructor(time, num = 1, fun = function () { }) {
         this.time = time;
         this.num = num;
         this.fun = fun;
         this.allow = true;
         this.exeArray = [];
      }
      exe(fun) {
         fun && (this.fun = this.fun);
         if (this.allow) {
            this.allow = false;
            this.fun();
            this.delay();
         }
         else {
            if (this.exeArray.length >= this.num - 1)
               return;
            this.exeArray.push(this.fun);
         }
      }
      delay() {
         setTimeout(() => {
            if (this.exeArray.length) {
               this.exeArray[0](this.allow, this.num, this.exeArray.length);
               this.exeArray.shift();
               this.delay();
            }
            else {
               this.allow = true;
            }
         }, this.time);
      }
   }
   const f = flying;
   window['f'] = flying;
   const mod = { f, delayExe, Count, meterTime, ranBool, ranMap, ranNum };
   if (window)
      Object.assign(window, mod);
}